#ifndef DEBRIDMANAGER_H
#define DEBRIDMANAGER_H

/*
Copyright (c) 2011, Stephane Albert
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the organization nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL STEPHANE ALBERT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <cstdlib>

#include "config.h"
#include "global.h"
#include "debridFetcherBase.h"
#include "debridFetcherAD.h"
#include "debridFetcherRD.h"

#include <map>
#include <list>

struct configSet {
    std::string username;
    std::string password;
    std::string service;
    std::string logfile;
    std::string logfailfile;
    std::string monitdir;
    std::string workingdir;
    std::string donedir;
    int maxretry;
    int loglevel;
}; typedef struct configSet configSet;

class debridManager {
    public:
        debridManager();
        ~debridManager();
        /*
         * Paswword ciphering/unciphering functions
         */
        /**
        * \brief Ciphers password.
        * \param rawPassword Password string to encode.
        * \return Ciphered password.
        * Ciphers password and add PASS_STR at the begining to identify ciphered pass from clear text.
        */
        static std::string cipherPass(const std::string &rawPassword);
        /**
        * \brief Unciphers password.
        * \param rawPassword Password string to decode.
        * \return Unciphered password or rawPassword if it doesn't seems ciphered.
        * Unciphers password and remove PASS_STR at the begining or rawPassword if it doesn't seems ciphered.
        */
        static std::string uncipherPass(const std::string &rawPassword);
        /*
         * Config utility
         */
        /**
        * \brief Decodes log level string to an int.
        * \param logLevelStr Log Level string to decode.
        * \return logLevel int.
        * Decodes every field in the string to reconstruct the value of the corresponding logLevel int.
        */
        static int decodeLogLevelStr(std::string logLevelStr);
        /**
        * \brief Encodes log level int to a string.
        * \param logLevel Log Level int to encode.
        * \return Log level string.
        * Split every flags from the int to generate the corresponding log level string.
        */
        static std::string encodeLogLevelToStr(int logLevel);
        debridFetcherBase* findService(const std::string& serviceName);
        /**
        * \brief Loads a config file.
        * \param configFilePath File to load.
        * \return true if loading is successful, false if it failed.
        * Opens the config file and loads it into memory.
        */
        bool loadConfig(const std::string& configFilePath);
        /**
        * \brief Configuration agent.
        * Spawns a wizard that guides you throught configuration.
        */
        void interactiveConfiguration();
        /*void loadConfig(const configSet configs[], int nbrOfConfigs);
        void loadDefaultConfig(const configSet &defaultConfigToLoad);*/
        /**
        * \brief Displays every configuration values.
        * Displays every configuration fiels, default and every threads. It will skip passwords if it's not in debug mode.
        */
        void displayConfig();
        /**
        * \brief Unload config from memory.
        * Unloads every configuration vars.
        */
        void unloadConfig();
        /**
        * \brief Save config to a file.
        * \param configFilePath File to save.
        * \param overwrite If overwrite is true save file will be overwritten, it will be appended.
        * \return true if saving is successful, false if it failed.
        * Save every configuration fields to a file.
        */
        bool saveConfig(const std::string& configFilePath, bool overwrite=true);
        bool start();
        void stop();
        /**
        * \brief Remove every fetching threads.
        * Remove every fetching threads.
        */
        void clearFetchers();
        static void loadlogLevelStrMap();
    private:
        static std::map<std::string, int> logLevelStrMap;
        std::list<configSet> loadedConfig;
        std::list<debridFetcherBase *> fetcherList;
        //Default settings
        configSet defaultConfig;
};

#endif // DEBRIDMANAGER_H
